/********************************************************************************
* @file    app_io.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2022-11-19
* @brief   IO功能
********************************************************************************/

#ifndef __APP_IO_H
#define __APP_IO_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

#include "ls_syscfg.h"

#include "bsp_gpio.h"
#include "bsp_exti.h"
/* Public Define -------------------------------------------------------------*/
typedef void(*io_irq_callback)(void);
/* Public Enum ---------------------------------------------------------------*/
typedef enum {
    IO_EVENT_NULL    = 0,
    IO_EVENT_IO_LOW, // 中断事件
    IO_EVENT_IO_HIGH,
    IO_EVENT_IO_KEY_SINGLE_CLICK, // 按键事件
    IO_EVENT_IO_KEY_TWO_CLICK,    // 双击
    IO_EVENT_IO_KEY_LONG_PRESS,   // 长按3秒
    IO_EVENT_IO_KEY_LONG_LONG_PRESS,   // 长按10秒
} io_event_t;

/* Typedef Struct ------------------------------------------------------------*/
typedef struct __PACKED {
    io_support_t support;
    uint8_t key_num;
    uint8_t matrix_x_num;
    uint8_t matrix_y_num;
} io_cfg_record_t; // 用于记录初始化过程中支持的功能和按键数量

typedef struct __PACKED {
    uint8_t save_support          : 1; // 0 -- 不支持保保存 1--支持保存
    uint8_t active_report_support : 1; // 0--不支持主动上报  1--支持主动上报
    uint8_t key_support           : 1; // 0 -- 不支持  1 -- 支持
    uint8_t matrix_key_support    : 1; // 0 -- 不支持  1 -- 支持
    uint8_t period_task_support   : 1; // 0 -- 不支持  1 -- 支持
    uint8_t swo_off               : 1; /* 0 -- 开启    1 -- 禁用
                                        如果禁用，将无法烧录和仿真。并且引脚将设置为输出状态。
                                        不可以设置输入，如果外部拉住，将无法恢复使用。*/
    uint8_t nonuse_default_cfg    : 1; // 是否使用默认配置 0--使用 1--不使用  如果flash没有配置，则使用默认配置
    uint8_t write_in              : 1; // flash是否写入 0--false 1--true
} io_flag_t; // 功能支持标记位

typedef struct __PACKED {
    uint8_t level         : 1; // 0--低电平 1--高电平
    io_event_t io_event   : 3;
    uint8_t reserve       : 4; // 预留
} io_func_t; // io类型 状态 事件

typedef struct __PACKED {
    uint8_t is_valid        : 1;  // 是否有效
    uint8_t is_repeat       : 1;  // 是否重复  0--无限重复  >1根据次数重复
    uint8_t start_task_event: 2;  // 0--低电平 1--高电平 2--翻转电平
    uint8_t stop_task_event : 2;  // 0--低电平 1--高电平 2--翻转电平
    uint8_t reserve         : 2;  // 预留
    uint8_t  id;            // 记录[ls_io_t]索引
    uint32_t start_time;    // 目标启动时间 秒级 【多少秒后，启动】
    uint32_t stop_time;     // 目标停止时间 秒级 【多少秒后，停止】
    uint32_t countdown;     // 秒级 计数器
} timer_period_task_t;

typedef struct __PACKED {
    bsp_gpio_t* cfg;
    io_type_t type[LS_IO_NUM];
    io_func_t func[LS_IO_NUM];
    io_irq_callback irq_cb[LS_IO_NUM];
    io_flag_t flag;
#if LS_IO_FLAG_PERIOD_TASK_SUPPORT
    timer_period_task_t period_task[LS_IO_FLAG_PERIOD_TASK_NUM];
    uint32_t period_task_time_ms;
#endif
} ls_io_t;
/* External Variables --------------------------------------------------------*/
extern ls_io_t g_io;

/* Public Macro --------------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
void app_io_init(void);
void app_io_deinit(void);
bool flash_read_app_io_all(void);
bool flash_write_app_io_all(void);

// 弱函数 ，当有按键事件时，就回调。默认功能，触发LED指示灯。如果外部重定义，触发LED指示灯将失效。
void key_event(void);
#endif
